import { config } from "@/utils/config.js"
import store from '@/store'

// HTTP 状态码
const httpCodeMessage = {
  400: "发出的请求有错误，服务器没有进行新建或修改数据的操作",
  401: "用户没有权限（令牌、用户名、密码错误）",
  403: "用户得到授权，但是访问是被禁止的",
  404: "发出的请求针对的是不存在的记录，服务器没有进行操作",
  406: "请求的格式不可得",
  410: "请求的资源被永久删除，且不会再得到的",
  422: "当创建一个对象时，发生一个验证错误",
  500: "服务器发生错误，请检查服务器",
  502: "网关错误",
  503: "服务不可用，服务器暂时过载或维护",
  504: "网关超时",
};

// 错误码
const miniCodeMessage = {
  11: "无权跨域",
  12: "网络出错",
  13: "超时",
  14: "解码失败",
  19: "HTTP错误",
  20: "请求已被停止/服务端限流",
};

// 是否在刷新中
let isRefreshing = false
// 重试队列
let requestQueue = []

/**
 * description: 网络请求封装
 * author: 83
 * createTime: 2022-03-10 3:09:20 ?F10: PM?
 * @param {object} options request参数
 * @return {Promise}
 */
const request = function (options) {
  return new Promise((resolve, reject) => {
		// 成功
		const success = async function (response) {
			const { statusCode, data } = response;
			if (statusCode == 200) {
				if (data.code != 200) {
					// token过期 需要重新刷新token
					if (data.code == 401) {
						// 当前没有进行刷新操作 则执行刷新
						if (!isRefreshing) {
							isRefreshing = true
							store.dispatch('user/refreshToken').then((res) => {
								// 刷新完成 执行所有队列
								requestQueue.forEach(cb => cb && cb())
								requestQueue = []
							}).catch((error) => {
								// 刷新失败 只能跳登录页重新登录
								uni.hideLoading()
								store.dispatch('user/resetToken').then(() => {
									uni.reLaunch({
										url: '/pages/login/index'
									})
								})
							}).finally(() => {
								setTimeout(() => isRefreshing = false, 1000)
							})
						}
						// 将所有失败的请求队列存到数组 等待刷新后再执行
						resolve(new Promise((resolve) => {
							requestQueue.push(() => {
								resolve(request(options))
							})
						}))
					} else if (data.code == 402) {
						// 刷新失败 只能跳登录页重新登录
						store.dispatch('user/resetToken').then(() => {
							uni.reLaunch({
								url: '/pages/login/index'
							})
						})
					}
					reject({
						error: data.code,
						message: data.msg || '服务忙碌中，请稍后再试！',
					});
				} else {
					resolve(data);
				}
			} else {
				reject({
					error: statusCode,
					message: data.msg || httpCodeMessage[statusCode],
				});
			}
		}
		// 失败
		const fail = function (response) {
			const { error, errorMessage = miniCodeMessage[error] } = response;
			reject({
				error,
				message: errorMessage,
			});
		}
		// 请求配置
		const requestParams = {
		  ...options,
		  success,
		  fail,
		};

    uni.request(requestParams);
  });
}

// 请求拦截器
uni.addInterceptor('request', {
	// 请求前触发
  invoke(options) {
		// #ifdef H5
		options.url = config.proxyPrefix + options.url
		// #endif
		// #ifndef H5
		options.url = config.baseApi + options.url
		// #endif
		if (!options.header) {
			options.header = {}
		}
		if (store.getters.token) {
			options.header['Authorization'] = 'Bearer ' + store.getters.token
		}
  },
	// 请求成功后
  success(response) {
    // 可以对相应数据更改
		// console.log('请求成功后', response)
  },
	// 请求失败后
  fail(err) {
		// console.log('请求失败后', err)
  },
})

export default request